package com.example.camerademoexcercies1.activity;

import android.Manifest;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.ImageFormat;
import android.graphics.SurfaceTexture;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.media.Image;
import android.media.ImageReader;
import android.media.MediaScannerConnection;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.HandlerThread;
import android.util.Size;
import android.view.Surface;
import android.view.TextureView;
import android.view.View;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;

import com.example.camerademoexcercies1.R;
import com.example.camerademoexcercies1.tool.LogTool;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Semaphore;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    /**
     * 区别：拍照时依旧stop session，添加imageReader的surface作为requestBuilder的target
     * 在启动session.request的时候，surface会自动调用Available监听，调用里面写好的线程，启动image类保存线程
     * */

    /**
     * 记录更新 ： 在看了CameraBasic之后得出结论（拍照之后停一下，在继续preview）:
     * 1.拍照的时候 先暂停让session暂停repeating ---> session.stopRepeating()
     * 2.让会话暂停记录：session.abortCapture()
     * 3.让拍照的session拥有自己的builder(设置参数，添加target)，自己的回调new Capture.Callback
     * 4.拍完照在拍照回调里让session继续repeating session.repeatingCapture()
     * 5.学到的就是将各种builder，session，callback全部都抽出来*/

    /**
     * 步骤：1 检查权限
     * 2 通过manager获取cameraId 和 cameraCharacteristic
     * 3 给画框设置监听，在通过characteristic得到和画框大小最匹配的size回传
     * 4 把最佳尺寸给imageReader解析器--用来解析合适尺寸、surfaceTexture--得到默认大小的最终画布surfaceView
     * 5 初始化一个后台循环线程
     * 6 cameraManager开启相机回调，在成功开启的方法中开始预览
     * 7 用cameraManager里的cameraDevice得到captureRequest--用来设置各种参数，同时必须设置一个target即surfaceView。和captureSession，传入surface和imageReader*/

    /**
     * 变量初始化
     * 1. CameraManager --- 系统服务管理器，用于检测，表征和连接到CameraDevices，可以得到cameraCharacteristics
     * 2. CameraCharacteristics --- 描述CameraDevice的属性，通过CameraManager获取某个摄像头的信息
     * 3. TextureView --- 画框
     * 4. ImageReader --- 用于解析和解码图像的抽象超类。将相机信息按最佳尺寸解析到Surface上
     * 5. Surface --- 提供嵌入视图层次结构内部的专用绘图表面。真正的画布
     * 6. cameraId --- 用于提供characteristics摄像头参数
     * 7. CameraDevice --- CameraDevice类是连接到Android设备的单个摄像头的代表
     * 8. mBackgroundHandler --- 把初始化的后台线程做looper循环调用，作为参数传给方法回调
     * 9. HandlerThread --- 一个后台线程
     */

    private CameraManager cameraManager;
    private CameraCharacteristics characteristics;
    private TextureView preview;
    private ImageReader imageReader;
    private Surface surfaceView;
    private String cameraId;
    private CameraDevice cameraDevice;
    private Handler mBackgroundHandler;
    private HandlerThread handlerThread;
    private CaptureRequest.Builder previewBuilder;
    private CameraCaptureSession previewSession;
    private Semaphore mCameraOpenCloseLock = new Semaphore(1);
    Size optimalSize;
    /**
     * 把回调抽离出来
     * 暂时煤球用
     */
    private final CameraDevice.StateCallback myStateCallBack = new CameraDevice.StateCallback() {
        @Override
        public void onOpened(@NonNull CameraDevice camera) {
            /**
             * openCamera()的回调,在相机打开后开始startPreview()*/
            mCameraOpenCloseLock.release();
            cameraDevice = cameraDevice;
            try {
                createPreviewSession(cameraDevice);
            } catch (CameraAccessException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onDisconnected(@NonNull CameraDevice camera) {
            mCameraOpenCloseLock.release();
            camera.close();
            cameraDevice = null;
        }

        @Override
        public void onError(@NonNull CameraDevice camera, int error) {
            mCameraOpenCloseLock.release();
            camera.close();
            cameraDevice = null;
        }
    };

    /**
     * 检查相机权限
     */
    private boolean hasPermission() {
        LogTool.log("权限检查");
        return ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED &&
                ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
    }

    /**
     * 入口
     */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initEvent();
        initCamera();//通过cameraManager获取相机ID，再通过ID获取Characteristic
//        当画布准备好之后就可以打开摄像头了
        preview.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() {
            /**判断是否可渲染*/
            @Override
            public void onSurfaceTextureAvailable(@NonNull SurfaceTexture surface,
                                                  int width, int height) {
                LogTool.log("传入TextureView尺寸、width：" + width + "、height：" + height + "\t以此计算分辨率");
                optimalSize = getOptimalSize(width, height);
                if (optimalSize != null) {
                    LogTool.log("获得最清晰（非最适配）尺寸 --- " + optimalSize.getWidth() +
                            " , " + optimalSize.getHeight());
                    surface.setDefaultBufferSize(optimalSize.getWidth(), optimalSize.getHeight()); //初始化默认大小的surface
                    surfaceView = new Surface(surface);
                    initImageReader();
                    /**说实话 获取了尺寸之后干嘛了？把最佳尺寸的值给了ImageReader、给了surface初始化了一下，
                     * 然后又赋值给了自定义的SurfaceView、然后就开启摄像头，
                     * 看了下教程 surfaceTexture是一种纹理，用来二次处理的，经过一系列磨皮，美颜
                     * 再传回给SurfaceView显示给TextureView*/
                    LogTool.log(" surfaceView配置完成，可以传入信息流，开启摄像头");
                    openCamera();
                } else {
                    say("未获取到符合标准的尺寸，系统停止运行");
                }
            }

            /**初始化imageReader*/
            private void initImageReader() {
                //                    在使用acquireLatestImage时maxImage不能小于2 从字面上和上面的知识我们了解到它是获取一张，丢弃一张。如果小于2的话可能会导致预期丢弃失败
                imageReader = ImageReader.newInstance(optimalSize.getWidth(),
                        optimalSize.getHeight(), ImageFormat.JPEG, 2);
                LogTool.log("imageReader初始化完成");
//                  给imageReader添加监听 在session.capture时，requestBuilder添加imageReader作为target,以此传入数据，并启动监听里的方法
                imageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
                    @Override
                    public void onImageAvailable(ImageReader reader) {
//                            执行图像保存线程
                        LogTool.log("执行图像保存线程");
//                        Image image = imageReader.acquireLatestImage();
//                        image.close();
                    mBackgroundHandler.post(new imageSaver(reader.acquireNextImage()));
                    }
                }, mBackgroundHandler);
            }

            @Override
            public void onSurfaceTextureSizeChanged(@NonNull SurfaceTexture surface, int width, int height) {

            }

            @Override
            public boolean onSurfaceTextureDestroyed(@NonNull SurfaceTexture surface) {
                return false;
            }

            @Override
            public void onSurfaceTextureUpdated(@NonNull SurfaceTexture surface) {

            }
        });
    }

    //初始化相机，获取cameraId和对应characteristics
    private void initCamera() {
        //获取manager
        cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
        //获取相机信息
        try {
            String[] idList = cameraManager.getCameraIdList();
            if (idList.length != 0) {
                cameraId = idList[CameraCharacteristics.LENS_FACING_FRONT];
//                LogTool.log("idList is :"+ Arrays.toString(idList));
                LogTool.log("找到摄像头 ID ：" + cameraId + ",通过cameraManager得到对应的Characteristics");
                characteristics = cameraManager.getCameraCharacteristics(cameraId);
            } else {
                LogTool.log("未找到可用摄像头◢◤");
            }
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

    /*@SuppressLint("MissingPermission")  屏蔽android lint错误
    @SuppressLint("NewApi")不一样。suppress只告诉lint，
     我这代码如果高于你的minsdkversion，那么请忽略编译错误。*/
    @SuppressLint("MissingPermission")
    private void openCamera() {
        if (cameraManager == null || cameraId == null) {
            Toast.makeText(this, "相机摄像头获取失败! cameraManager或cameraId为空", Toast.LENGTH_SHORT).show();
        } else {
            startBackgroundThread();
            LogTool.log("顺序检查2");
            if (hasPermission()) { //为什么又要检测一次...
                LogTool.log("顺序检查3");
                try {
                    //之前用cameraID获取了最佳尺寸，现在用来开启摄像头
                    cameraManager.openCamera(cameraId, new CameraDevice.StateCallback() {
                        @Override
                        public void onOpened(@NonNull CameraDevice camera) {
                            LogTool.log("通过manager开启相机，得到cameraDevice，开始预览创建全局session和previewBuilder");
                            cameraDevice = camera;
                            try {
                                createPreviewSession(camera);
                            } catch (CameraAccessException e) {
                                e.printStackTrace();
                            }
                        }

                        @Override
                        public void onDisconnected(@NonNull CameraDevice camera) {

                        }

                        @Override
                        public void onError(@NonNull CameraDevice camera, int error) {

                        }
                    }, mBackgroundHandler);
                } catch (CameraAccessException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    //获取最佳相机尺寸
    private Size getOptimalSize(int textureWidth, int textureHeight) {
        if (characteristics == null) {
            LogTool.log("Characteristics为空,可能因为CameraManager未找到符合的摄像头ID");
            return null;
        } else {
            float aspectRatio = (float) textureWidth / textureHeight;
            /**
             * SCALER_STREAM_CONFIGURATION_MAP --- //
             *              此相机设备支持的可用流配置; 还包括每种格式/尺寸组合的最小帧持续时间和停顿持续时间。
             *             不可变类用于存储可用流 configurations以设置 Surfaces以创建
             *              capture session 和 createCaptureSession(List , CameraCaptureSession.StateCallback, Handler)*/
            StreamConfigurationMap configurationMap = //一份详细的配置表
                    characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
            Size[] sizeList = configurationMap.getOutputSizes(SurfaceTexture.class); //提供一个可输出Size的类
            List<Size> readyList = new ArrayList<>();
/*            int standWidth = Integer.MAX_VALUE;
            int standHeight = Integer.MAX_VALUE;
            for (Size size : sizeList) {
//                计算当前遍历分辨率与画布的差距
                int width_differ = Math.abs(size.getWidth() - textureHeight); //比较手机长度
                int height_differ = Math.abs(size.getHeight() - textureWidth); //比较手机宽度
                LogTool.log("当前遍历尺寸------------------手机长:(" + size.getWidth() + ")手机宽:(" + size.getHeight()+")");
                if (width_differ <= standWidth) { //先比较手机长度最接近的
                    LogTool.log("当前尺寸的手机长度标准差( "+standWidth+" )更小的size;屏幕长:（" + size.getWidth() + "）屏幕宽：(" + size.getHeight()+")");
                    standWidth = width_differ;
                    if (height_differ <= standHeight) { //再比较手机宽度最接近的
                        LogTool.log("当前尺寸的手机宽度标准差( "+standHeight+" )更小的size;屏幕长:（" + size.getWidth() + "）屏幕宽：(" + size.getHeight()+")");
                        standHeight = height_differ;
                        sizeList[0] = size;
                    }
                }
            }
            return sizeList[0];*/
//            先找尺寸接近的，再找其中分辨率最高的
            float bestRatio = (float) textureHeight / textureWidth;
            int maxSize = 0; //最大手机长度缓存 我的手机原生的最佳宽高比是1.333333
            for (Size size : sizeList) {
                LogTool.log("尺寸:" + size.toString() + "和最佳比例（" + bestRatio + "）的差为" +
                        Math.abs(((float) size.getWidth() / size.getHeight() - bestRatio)));
                if (Math.abs(((float) size.getWidth() / size.getHeight() - bestRatio)) < 0.3) {
                    readyList.add(size);
                }
            }
            LogTool.log("最佳比例差小于0.3的尺寸有:" + readyList.toString());
            for (Size size : readyList) {
                if (size.getWidth() > maxSize) {
                    maxSize = size.getWidth();
                    sizeList[0] = size;
                }
            }
            return sizeList[0];
        }
    }

    //初始化事件
    private void initEvent() {
        if (hasPermission()) {
            LogTool.log("拥有Camera权限和照片写入权限");
        } else {
            LogTool.log("开始请求权限");
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1000);
        }
        LogTool.log("检查是否顺序执行");
        findViewById(R.id.btn_takePhoto).setOnClickListener(this);
        findViewById(R.id.btn_stopPreview).setOnClickListener(this);
        findViewById(R.id.btn_startPreview).setOnClickListener(this);
        preview = findViewById(R.id.preview);
    }

    //    点击监听
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn_takePhoto:
                say("开一个绘画，用作capture，投影到textureView上---拍照");
                takeAPhoto();
                break;
            case R.id.btn_stopPreview:
                say("停止预览会话的循环请求");
                break;
            case R.id.btn_startPreview:
                say("预览session再次调用preview请求");
                try {
                    previewSession.stopRepeating();
                    previewSession.abortCaptures();
                } catch (CameraAccessException e) {
                    e.printStackTrace();
                }
        }
    }

    //    创建全局session，同时给surface和imageReader(不显示，用于拍照获取)传输数据流
    private void createPreviewSession(@NonNull CameraDevice camera) throws CameraAccessException {
        //进入回调线程内的具体执行
        previewBuilder = camera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
        previewBuilder.addTarget(surfaceView);
        previewBuilder.set(CaptureRequest.CONTROL_AE_MODE,
                CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);//自动开启闪光灯
        previewBuilder.set(CaptureRequest.CONTROL_AE_MODE,
                CaptureRequest.CONTROL_AF_MODE_AUTO);//自动聚焦
        previewBuilder.set(CaptureRequest.STATISTICS_FACE_DETECT_MODE,//人脸检测模式
                CameraCharacteristics.STATISTICS_FACE_DETECT_MODE_SIMPLE);

        camera.createCaptureSession(Arrays.asList(surfaceView,imageReader.getSurface()),
                new CameraCaptureSession.StateCallback() {
                    /**
                     * 真正的核心步骤：配置相机参数，开启循环会话（绘画）*/
                    @Override
                    public void onConfigured(@NonNull CameraCaptureSession session) {
                        try {
                            previewSession = session;
                            previewSession.setRepeatingRequest(previewBuilder.build(),
                                    null, mBackgroundHandler);
                            //由于不需要做额外的处理所以为null而不是回调CameraCaptureSession.CaptureCallback()
                        } catch (CameraAccessException e) {
                            e.printStackTrace();
                        }
                    }
                    @Override
                    public void onConfigureFailed(@NonNull CameraCaptureSession session) {

                    }
                }, mBackgroundHandler);
    }

    //    直接拿取预览的bitmap直接存，也算是一种拍照吧
    public void takeAPhoto(){
//        不再用session创建一个拍照的request，当然也就没有对应的builder可以传参，图片质量没有保障
//        这样太low了，如果直接保存预览图像的话，应该从预览的requestResult开始着手
        LogTool.log("直接获取textureView的bitmap");
        saveImage(preview.getBitmap());
    }

    //传统拍照
    //    拍照 session传入拍照builder，设置target为imageReader 以此不用暂停surfaceView而从imageReader里获取图像
//    private void takeAPhoto() {
//        try {
//            previewSession.stopRepeating();
//            previewSession.abortCaptures();  //尽快丢弃所有当前挂起和进行中的捕获。
//            LogTool.log("暂停预览，需要用session拍照");
////            拍照建立一个自己的builder
//            final CaptureRequest.Builder captureBuilder =
//                    cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE); //此参数更注重画质而非帧数
////            拍照的target设置为imageReader的surface
//            captureBuilder.addTarget(imageReader.getSurface());
//            LogTool.log("添加captureBuilder的target为imageReader");
////            设置builder的拍照参数
//            captureBuilder.set(CaptureRequest.CONTROL_AF_MODE,
//                    CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE); //自动对焦
//            //          拥有属于拍照自己的callback
//            final CameraCaptureSession.CaptureCallback uselessCallBack = new CameraCaptureSession.CaptureCallback() {
//                @Override
//                public void onCaptureCompleted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull TotalCaptureResult result) {
//                    LogTool.log("拍照完成回调");
////                    使用imageReader作为输出源，在capture时作为target，并在之前设置好监听，
////                    一旦被传入数据就讲imageReader的请求image传入存储图片线程并用mBackgroundHandler调用.
////                    所以为什么要这么复杂而不是直接让textView获取一张bitmap通过BitmapFactory.compress直接保存呢？
////                    saveImage(preview.getBitmap());
//                    unlockFocus(); //解除当前拍照占用状态
//                }
//            };
//            LogTool.log("拍照请求");
//            previewSession.capture(captureBuilder.build(), uselessCallBack, mBackgroundHandler);
//        } catch (CameraAccessException e) {
//            e.printStackTrace();
//        }
//    }

    //    创建保存图片的线程
    public class imageSaver implements Runnable {
        private Image mImage;

        public imageSaver(Image image) {
            mImage = image;
        }

        @Override
        public void run() {
//        getPlanes()返回一个Plane[]矩阵数组 拿取第一个Plane使用getBuffer()获得该像素矩阵的ByteBuffer--字节缓存
            ByteBuffer buffer = mImage.getPlanes()[0].getBuffer();
//        返回该缓冲区最大数据长度
            byte[] data = new byte[buffer.remaining()];
            buffer.get(data);
            File finalFile = null; //最终文件路径
            //路径尾部
            String tailName = System.currentTimeMillis() + ".jpg";
            //DCIM的根目录 /storage/emulated/0/DCIM
            File root = new File(String.valueOf(Environment.getExternalStoragePublicDirectory(
                    Environment.DIRECTORY_DCIM)), "CameraTestStorage");
            //拿到根目录开始操作输出流
            FileOutputStream fos = null;

            if (root.isDirectory() || root.mkdir()) {
                LogTool.log("根目录+" + root.toString() + "+创建成功");
                finalFile = new File(root, tailName); //absolute路径
                try {
                    fos = new FileOutputStream(finalFile);
                    fos.write(data, 0, data.length);
                    LogTool.log(finalFile.toString()+"保存成功");
//                    通知系统图库更新
                    notifyUpdata(finalFile);
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
//                    关闭输出流 清空图像file缓存
                    finalFile = null;
                    if (fos != null) {
                        try {
                            fos.close();
                            fos = null;
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            } else {
                LogTool.log("根目录+" + root.toString() + "+创建失败");
            }
        }

        private void notifyUpdata(File file) {
            //                    通知图库更新
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) { //要求sdk大于25 android7.0及以上 储存方式发生了改变
                MediaScannerConnection.scanFile(MainActivity.this, new String[]{file.getAbsolutePath()}, null,
                        new MediaScannerConnection.OnScanCompletedListener() {
                            @Override
                            public void onScanCompleted(String path, Uri uri) {
                                Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
                                mediaScanIntent.setData(uri);
                                sendBroadcast(mediaScanIntent); //扫描完毕，发送广播通知图库更新
                                LogTool.log("扫描更新完毕");
                            }
                        });
            } else {
                LogTool.log("设备的版本低于Android7.0");
                String relationDir = file.getParent();
                assert relationDir != null;
                File file1 = new File(relationDir);
                sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.fromFile(file1.getAbsoluteFile())));
            }
        }
    }

    //    存图核心方法
    private void saveImage(Bitmap bitmap) {
        File file = null; //最终文件路径
        String fileName = System.currentTimeMillis() + ".jpg"; //路径尾部
        File root = new File(String.valueOf(Environment.getExternalStoragePublicDirectory(
                Environment.DIRECTORY_DCIM)), "CameraTestStorage"); //DCIM的根目录 /storage/emulated/0/DCIM
        LogTool.log("image root path is " + root.toString());
        if (root.isDirectory() || root.mkdir()) {
            LogTool.log("根目录创建成功");
            file = new File(root, fileName);
            LogTool.log("this is complete image path is " + file.toString());
            try {
                FileOutputStream fos = new FileOutputStream(file);
                bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos); //100%意为不压缩 压缩图片到JPG模式存到指定file目录
                fos.flush(); //清空关闭
                fos.close();
                say("图片存储到:" + file.toString());
            } catch (IOException e) {
                e.printStackTrace();
            }
//放图片到系统图库 不是多余的吗
//            try {
//                MediaStore.Images.Media.insertImage(getContentResolver(), //getContentResolver是啥
//                        file.getAbsolutePath(), "toImageFolderPick.jpg", null); //file不已经是完整路径了吗 为啥还要跟fileName
//                LogTool.log("放入成功");
//            } catch (FileNotFoundException e) {
//                e.printStackTrace();
//            }

//                    通知图库更新
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) { //要求sdk大于25 android7.0及以上 储存方式发生了改变
                MediaScannerConnection.scanFile(MainActivity.this, new String[]{file.getAbsolutePath()}, null,
                        new MediaScannerConnection.OnScanCompletedListener() {
                            @Override
                            public void onScanCompleted(String path, Uri uri) {
                                Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
                                mediaScanIntent.setData(uri);
                                sendBroadcast(mediaScanIntent); //扫描完毕，发送广播通知图库更新
                                LogTool.log("扫描更新完毕");
                            }
                        });
            } else {
                LogTool.log("设备的版本低于Android7.0");
                String relationDir = file.getParent();
                assert relationDir != null;
                File file1 = new File(relationDir);
                sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.fromFile(file1.getAbsoluteFile())));
            }
        } else {
            LogTool.log("根目录创建失败");
        }
    }

    //    重启预览 -- 前提是previewBuilder配置完善，mBackgroundThread正常运行
    private void unlockFocus() {
        try {
            previewSession.setRepeatingRequest(previewBuilder.build(), null, mBackgroundHandler);
            LogTool.log("重启预览");
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

    //    至今不太懂为什么必须要创建这个线程
    private void startBackgroundThread() {
        handlerThread = new HandlerThread("CameraThread");
        handlerThread.start();
        mBackgroundHandler = new Handler(handlerThread.getLooper());
        LogTool.log("HandlerThread初始化完成,并开启循环模式，在回调中传入mBackgroundHandler");
    }

    //清空handler
    private void stopBackgroundThread() {
        if (handlerThread != null) {
            handlerThread.quitSafely();
            try {
                handlerThread.join();
                handlerThread = null;
                mBackgroundHandler = null;
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    //退回桌面销毁线程 停止拍摄
    @Override
    protected void onDestroy() {
        super.onDestroy();
        stopBackgroundThread();
    }

    public void say(String s) {
        Toast.makeText(MainActivity.this, s, Toast.LENGTH_SHORT).show();
    }

    private volatile static MainActivity singleton;

}